﻿using System.Collections.Generic;
using System.ComponentModel;
using System;
using System.Collections;
using System.Web.Configuration;
using System.IO;
using System.Data.SqlClient;
using System.Text.RegularExpressions;

namespace ScrumFactory.Setup.Custom {

    [RunInstaller(true)]
    public partial class Installer : System.Configuration.Install.Installer {

        public Installer() {
            InitializeComponent();
        }

        private int dbCount = 0;
        private string DBName = "ScrumFactory";

        private string ServerName {
            get {
                return Context.Parameters["DB_SERVER"];
            }
        }

        private string DBUser {
            get {
                return Context.Parameters["DB_USER"];
            }
        }

        private string DBPassword {
            get {
                return Context.Parameters["DB_PASS"];
            }
        }

        
        private string AdminConnectionString {
            get {
                return String.Format("Data Source={0};User ID={1};Password={2}", ServerName, DBUser, DBPassword);
            }
        }

        private string SiteConnectionString {
            get {
                return "metadata=res://*/ScrumFactory.csdl|res://*/ScrumFactory.ssdl|res://*/ScrumFactory.msl;provider=System.Data.SqlClient;provider connection string=\"" + SiteSimpleConnectionString + "\"";
            }
        }

        private string SiteSimpleConnectionString {
            get {
                return String.Format("Data Source={0};Initial Catalog={1};User ID=sf_db_user;Password=sf;MultipleActiveResultSets=True", ServerName, DBName);
            }
        }

        private string WebAppName {
            get {
                return Context.Parameters["TARGETVDIR"];
            }
        }

        private string WebAppPhysicalPath {
            get {
                return Context.Parameters["TARGETDIR"] + "\\App_Data\\DB_SCRIPT";
            }
        }

        private System.DirectoryServices.DirectoryEntry GetIIsSiteEntry() {
            string targetSite = Context.Parameters["TARGETSITE"];
            
            if (targetSite.StartsWith("/LM/"))
                targetSite = targetSite.Substring(4);

            return new System.DirectoryServices.DirectoryEntry("IIS://LocalHost/" + targetSite);
        }

        private string SiteName {
            get {
                System.DirectoryServices.DirectoryEntry entry = GetIIsSiteEntry();

                if (entry == null)
                    return "http://localhost";

                System.DirectoryServices.PropertyValueCollection pvc = entry.Properties["ServerBindings"];
                if (pvc.Count == 0)
                    return "http://localhost/";

                string[] Bits = pvc[0].ToString().Split(':');
                string IPAddress = Bits[0];
                string TCPIPPort = Bits[1];
                string hostHeader = Bits[2];

                if (hostHeader.Length == 0)
                    hostHeader = "localhost";


                return "http://" + hostHeader + ":" + TCPIPPort + "/";


            }
        }

        private string SetScriptDBName(string script) {
            while (DBAlreadyCreated)
                GoToNextDBName();
            script = script.Replace("[ScrumFactory]", "[" + DBName + "]");
            return script;
        }

        private bool DBAlreadyCreated {
            get {
                try {
                    SqlConnection cnn = new SqlConnection(SiteSimpleConnectionString);
                    cnn.Open();
                    cnn.Close();
                }
                catch (Exception) {
                    return false;
                }
                return true;
            }
        }

        private void GoToNextDBName() {            
            dbCount++;
            DBName = "ScrumFactory_" + dbCount;            
        }

        private void CreateDB() {

            string dbScriptPath = WebAppPhysicalPath + "\\DB_SCRIPT.sql";
            string script = File.ReadAllText(dbScriptPath);

            script = SetScriptDBName(script);

            // split script on GO command
            IEnumerable<string> commandStrings = Regex.Split(script, "^\\s*GO\\s*$", RegexOptions.Multiline | RegexOptions.IgnoreCase);

            SqlConnection cnn = new SqlConnection(AdminConnectionString);
            cnn.Open();
            foreach (string commandString in commandStrings) {
                if (commandString.Trim() != "") 
                    new SqlCommand(commandString, cnn).ExecuteNonQuery();                
            }
            cnn.Close();
          
           
        }

        private void UpdateWebConfig() {

            // Retrieve "Friendly Site Name" from IIS for TargetSite
            System.DirectoryServices.DirectoryEntry entry = GetIIsSiteEntry();
            string friendlySiteName = entry.Properties["ServerComment"].Value.ToString();

            // Open Application's Web.Config
            System.Configuration.Configuration config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("/" + WebAppName, friendlySiteName);

            config.ConnectionStrings.ConnectionStrings["ScrumFactoryEntitiesConnectionString"].ConnectionString = SiteConnectionString;
            
            // Persist web.config settings
            config.Save();
        }

        [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
        public override void Install(IDictionary stateSaver) {
            base.Install(stateSaver);

            try {
                CreateDB();
                UpdateWebConfig();
            }
            catch(Exception ex) {                          
                throw new System.Configuration.Install.InstallException(ex.Message);                                
            }

        }

        [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
        public override void Commit(IDictionary savedState) {
            base.Commit(savedState);
            
            try {
                string serverHomePage = SiteName + WebAppName;
                System.Diagnostics.Process.Start(serverHomePage);
            } catch(System.Exception) {}
        }

        [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
        public override void Rollback(IDictionary savedState) {
            base.Rollback(savedState);
        }

        [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
        public override void Uninstall(IDictionary savedState) {
            base.Uninstall(savedState);
        }
    }
}
